import net from 'net';
import EventEmitter from 'events';


export default class Socket {
    private header = '2878'
    private suffix = '1555'
    private totalData:number[] = [];
    private totalChunk:string = ''
    public deviceId:string = ''
    public activeTime:number = 0
    private parseIng:boolean = false;
    private eventEmitter:EventEmitter;
    constructor(private sock:net.Socket) {
        this.eventEmitter = new EventEmitter()
        this.init()

    }

    on<T>(event:'data'|'destroy', listener:(data:T) => void) {
        this.eventEmitter.on(event, listener)
    }

    

    init() {
        this.sock.setTimeout(600000)
        this.sock.on('data', buff => {
			console.log('收到数据')
			console.log(buff.toString())
            this.activeTime = (new Date()).getTime()
            //this.totalData.push(...Array.from(buff))

            const chunk = buff.toString('hex').trim()
            this.totalChunk += chunk
            this.parse()

            //let _data = this.totalChunk + chunk
            // while(true) {
            //     let result = this.decode(_data)
            //     console.log(result)
            //     if(result == 0) { //还没有接收完整的包
            //         this.totalChunk = _data
            //         break
            //     }else if(result == 1) { //数据非法,关闭连接
            //         this.destroy()
            //         break
            //     }else  {
            //         if(typeof result == 'object') {
            //             this.eventEmitter.emit('data', {cmd : result.cmd, packDir : result.packDir, type : result.type, timestamp : result.timestamp, deviceId : result.deviceId, data : result.data})
            //             _data = result.surplusChunk
            //             continue
            //         }
            //     }
            // }

        })

        this.sock.on('timeout', () => {
            console.log('timeout')
            this.destroy()
        })

        this.sock.on('error', (error) => {
            console.log(error)
            this.destroy()
        })

        this.sock.on('close', (had_error) => {
            console.log('关闭 close')
            console.log(had_error)
            this.eventEmitter.emit('destroy')
        })
    }

    destroy() {
        console.log('it is destroy')
        this.sock.destroy()
    }

    send(data:string) {
        this.sock.write(Buffer.from(data, 'hex'))
    }


    parseData() {
        if(this.parseIng) return
        this.parseIng = true



    }

    decodeData() {
        let len = this.totalData.length
        if(len < 45) return 0 //还不是完整的包

        let buffer = Buffer.from(this.totalData)

        if(buffer.readUInt8(0) != 40 || buffer.readUInt8(1) != 120) { //头部不合法
            console.log('header illegal')
            return 1
        }


        const packDir = buffer.readUInt8(2)
        if(packDir != 0) { //帧包方向不合法
            console.log('packDir illegal')
            return 1
        }

        const type = buffer.readUInt8(3)
        if(type != 1 && type != 2) { //帧包类型不合法
            console.log('type illegal')
            return 1
        }


        const timestamp = buffer.slice(4, 10)




    }


    parse() {
        if(this.parseIng) return
        this.parseIng = true
        let result = this.decode(this.totalChunk)

        if(result == 1) { //数据非法,关闭连接
            console.log('关闭')
            this.destroy()
            return
        }

        if(typeof result == 'object') {
            this.eventEmitter.emit('data', {cmd : result.cmd, packDir : result.packDir, type : result.type, timestamp : result.timestamp, deviceId : result.deviceId, data : result.data})
            this.totalChunk = this.totalChunk.substr(result.packeLength)
            
        }

        this.parseIng = false

        if(this.totalChunk.length > 20) {
            this.parse()
        }
        

    }

    decode(chunk:string) {
        const headerLen = this.header.length
        const packDirLen = 2
        const typeLen = 2
        const timestampLen = 12
        const followLengthLen = 4

        let header = chunk.substr(0, headerLen)
        if(header.length != headerLen) return 0 //包还没接收完

        if(header !== this.header) {
            console.log('it is header')
            console.log(header)
            return 1 //数据非法
        }

        let packDir:PackDir = chunk.substr(headerLen, packDirLen) as PackDir
        if(packDir.length != packDirLen) return 0 //包还没接收完
        if(packDir !== '00' && packDir !== '01') {
            console.log(packDir)
            console.log('it is packDir')
            return 1 //数据非法
        }

        let msgType:MsgType = chunk.substr(headerLen + packDirLen, typeLen) as MsgType
        if(msgType.length != typeLen) return 0 //包还没接收完
        if(msgType !== '01' && msgType !== '02') {
            console.log(msgType)
            console.log('it is type')
            return 1 //数据非法
        }

        let timestamp = chunk.substr(headerLen + packDirLen + typeLen, timestampLen)
        if(timestamp.length != timestampLen) return 0 //包还没接收完

        let length = chunk.substr(headerLen + packDirLen + typeLen + timestampLen, followLengthLen)
        if(length.length != followLengthLen) return 0 //包还没接收完

        let followLen = parseInt(length, 16) * 2 //后续字符串的长度

        let followStr = chunk.substr(headerLen + packDirLen + typeLen + timestampLen + followLengthLen, followLen) //后续的字符串
        if(followStr.length != followLen) return 0 //包还没接收完
        if(followStr.indexOf(this.suffix) != (followLen - this.suffix.length)) {
            console.log('it is followStr')

            return 1 //数据非法
        }


        let encrypt = followStr.substr(0, 2)
        //let reserved = followStr.substr(2, 16)
        let deviceId = followStr.substr(18, 40)
        let data = followStr.substr(58, followLen - 58 - 8)
        let cmd = data.substr(0, 4)


        let packeLength = headerLen + packDirLen + typeLen + timestampLen + followLengthLen + followLen

        //let packChunk = chunk.substr(0, packeLength)
        //let surplusChunk = chunk.substr(packeLength)

        return {
            packeLength,
			packDir,
            timestamp,
            type : msgType,
            deviceId,
            cmd,
            data : data.substr(4), //截取cmd后才是真正的data
            //surplusChunk,
            //packChunk
        }

    }

    encode(msgType:MsgType, data:string) {
        // let date = new Date()
        // let time = Math.floor(date.getTime() / 1000)
        // let millisecond = date.getMilliseconds()
        // let packDir:PackDir = '01'
        // let timestamp = numToHex(time, 8) + numToHex(millisecond, 4)
        // let encrypt = numToHex(0, 2)
        // let reserved = numToHex(0, 16)

    }
    
}